package gestionOrdres;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import metiers.Axe;
import metiers.Concept;
import metiers.typeAssociationConcept;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.RDFWriter;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.SimpleSelector;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.util.FileManager;

/**
 * 
 * @author Freddy KAKOU
 * 
 */
public class LectureFichierOrdre {

	/** l'unique instance de la classe */
	private static LectureFichierOrdre uniqueLecture;
	/** La liste des axess */
	private List<Axe> listeAxes;
	/** la liste des concepts */
	private List<Concept> listeConcepts;
	private Model model = ModelFactory.createDefaultModel();
	private Model donnees = ModelFactory.createDefaultModel();

	/**
	 * Contructeur de la classe
	 */
	private LectureFichierOrdre() {
		listeAxes = new ArrayList<Axe>();
		listeConcepts = new ArrayList<Concept>();
		parser();

	}

	public static synchronized LectureFichierOrdre getUniqueLecture() {
		if (uniqueLecture == null) {
			uniqueLecture = new LectureFichierOrdre();

		}
		System.out.println("uniqueLectureOrdre " + uniqueLecture);
		return uniqueLecture;
	}

	/**************************** Methode ***************/

	/**
	 * Méthode qui parse le fichier d'ontologie
	 */
	public void parser() {

		// création du modèle de données et du modèle de description

		/*-----------------------------------------------------------------------------*/
		/*
		 * Chargement des fichiers qui contiennent les données et leur
		 * description
		 */
		String inputFileName = System.getProperty("pfe.fichierOntologie.dir")
				+ "PFE.owl";
		// on utilise le FileManager pour trouver le fichier .owl
		InputStream in = FileManager.get().open(inputFileName);
		if (in == null) {
			throw new IllegalArgumentException("File: " + inputFileName
					+ " not found");
		}

		// lecture du fichier de description au format RDF/XML
		// On stocke la description dans la variable model
		model.read(in, null);

		inputFileName = System.getProperty("pfe.fichierOntologie.dir")
				+ "donneesCourantes.xml";
		// on utilise le FileManager pour trouver le fichier .owl
		in = FileManager.get().open(inputFileName);
		if (in == null) {
			/* lecture et écriture dans le fichier de données */
			RDFWriter w = model.getWriter("RDF/XML-ABBREV");
			w.setProperty("attributeQuoteChar", "'");
			w.setProperty("showXMLDeclaration", "true");
			w.setProperty("tab", "1");
			w.setProperty(
					"blockRules",
					"daml:collection,parseTypeLiteralPropertyElt,"
							+ "parseTypeResourcePropertyElt,parseTypeCollectionPropertyElt");
			EcritureFichier lect = new EcritureFichier(
					System.getProperty("pfe.fichierOntologie.dir"),
					"donneesCourantes.xml");
			System.out.println("parser 1");
			w.write(model, lect.getFlux(), "RDF/XML-ABBREV");
			System.out.println("parser 2");
			in = FileManager.get().open(inputFileName);
			System.out.println("parser 3");
		}

		// lecture du fichier de données au format RDF/XML
		// on stocke les données dans la variable donnees
		System.out.println("parser 4");
		donnees.read(in, null, "RDF/XML-ABBREV");
		System.out.println("parser 5");

		/*
		 * ------------------------fine de chargement des
		 * fichiers---------------------------------
		 */
		/*-----------------------------------------------------------------------------------------*/

		/*------------------------------------DEBUT DU PARSING DU FICHIER---------------------------*/
		String rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
		String base = "http://onthologieContextePFE.owl#";

		System.out.println("parser 6");
		Property propType = model.getProperty(rdf + "type");
		Property propEffectifCompl = model.getProperty(base
				+ "effectifTotalEnComplementaire");
		Property propEffectifPrinc = model.getProperty(base
				+ "effectifTotalEnPrincipal");
		Property propNombreRequetes = model
				.getProperty(base + "nombreRequetes");
		Property propAxePrincipal = model.getProperty(base
				+ "aPourAxeEnPrincipal");
		Property propAxeComplementaire = model.getProperty(base
				+ "aPourAxeEnComplementaire");
		Property propNbNA = model.getProperty(base
				+ "aPourNombreValeursManquantes");
		Property propConceptConcerne = model.getProperty(base
				+ "aPourConceptConcerne");
		Property propStatistiqueX2 = model.getProperty(base
				+ "aPourStatistiqueX2");
		Property propNombreChoix = model.getProperty(base + "aNombreChoix");
		Property propClassement = model.getProperty(base + "aPourClassement");

		Resource concept = model.getResource(base + "Concept");
		System.out.println("parser 7");

		// On récupère tous les concepts (toutes les ressources qui sont de
		// types concepts)
		StmtIterator listCOncepts = donnees.listStatements(new SimpleSelector(
				null, propType, concept));
		
		System.out.println("parser 8");

		while (listCOncepts.hasNext()) {
			Statement ligne = listCOncepts.next();

			// Pour chaque concept existant dans le fichier, on le récupère et
			// on le crée sous forme d'objet Java
			Concept c = new Concept(ligne.getSubject().getLocalName());

			// On regarde si ce concept est déjà la liste des concepts, sinon on
			// le rajoute
			if (!listeConcepts.contains(c)) {
				listeConcepts.add(c);
			}

			// On récupère l'index du concept
			int indexConcept = listeConcepts.indexOf(c);

			// On remplit le nombre de requêtes s'il existe
			StmtIterator testNombreRequetes = donnees
					.listStatements(new SimpleSelector(ligne.getSubject(),
							propNombreRequetes, (RDFNode) null));
			if (testNombreRequetes.hasNext()) {
				int nbRequetes = testNombreRequetes.next().getObject()
						.asLiteral().getInt();

				listeConcepts.get(indexConcept).setNombreRequetes(nbRequetes);
			}

			// On remplit l'effectif principal s'il existe
			StmtIterator testEffectifPrinc = donnees
					.listStatements(new SimpleSelector(ligne.getSubject(),
							propEffectifPrinc, (RDFNode) null));
			if (testEffectifPrinc.hasNext()) {
				int effPrinc = testEffectifPrinc.next().getObject().asLiteral()
						.getInt();
				listeConcepts.get(indexConcept).setEffectifTotalPrinc(effPrinc);
			}

			// On remplit l'effectif complémentaire s'il existe
			StmtIterator testEffectifComp = donnees
					.listStatements(new SimpleSelector(ligne.getSubject(),
							propEffectifCompl, (RDFNode) null));
			if (testEffectifComp.hasNext()) {
				int effComp = testEffectifComp.next().getObject().asLiteral()
						.getInt();
				listeConcepts.get(indexConcept).setEffectifTotalComp(effComp);
			}

			// On va maintenant chercher les axes principaux
			StmtIterator listAxesPrincipaux = donnees
					.listStatements(new SimpleSelector(ligne.getSubject(),
							propAxePrincipal, (Resource) null));
			
			System.out.println("parser 9");

			while (listAxesPrincipaux.hasNext()) {
				Statement axePrincipal = listAxesPrincipaux.next();
				int nbNA = 0;
				int classement = 0;
				double stat = 0;
				Concept conceptConcerne = new Concept("");
				int nbChoix = 0;

				// On récupère le concept concerne
				StmtIterator testConceptConcerne = donnees
						.listStatements(new SimpleSelector(axePrincipal
								.getObject().asResource(), propConceptConcerne,
								(RDFNode) null));
				if (testConceptConcerne.hasNext()) {
					conceptConcerne = new Concept(testConceptConcerne.next()
							.getResource().getLocalName());
				}

				// On récupère le nombre de valeur manquantes
				StmtIterator testNbNA = donnees
						.listStatements(new SimpleSelector(axePrincipal
								.getObject().asResource(), propNbNA,
								(RDFNode) null));
				if (testNbNA.hasNext()) {
					nbNA = testNbNA.next().getObject().asLiteral().getInt();
				}

				// on récupère la statistique
				StmtIterator testStat = donnees
						.listStatements(new SimpleSelector(axePrincipal
								.getObject().asResource(), propStatistiqueX2,
								(RDFNode) null));
				if (testStat.hasNext()) {
					stat = testStat.next().getObject().asLiteral().getDouble();
				}

				// On récupère le classement
				StmtIterator testClassement = donnees
						.listStatements(new SimpleSelector(axePrincipal
								.getObject().asResource(), propClassement,
								(RDFNode) null));
				if (testClassement.hasNext()) {
					classement = testClassement.next().getObject().asLiteral()
							.getInt();
				}

				// On récupère le nombre de choix
				StmtIterator testNbChoix = donnees
						.listStatements(new SimpleSelector(axePrincipal
								.getObject().asResource(), propNombreChoix,
								(RDFNode) null));
				if (testNbChoix.hasNext()) {
					nbChoix = testNbChoix.next().getObject().asLiteral()
							.getInt();
				}

				// On crée l'objet Java axe
				if (!listeConcepts.contains(conceptConcerne)) {
					listeConcepts.add(conceptConcerne);
				}

				int indexConceptConcerne = listeConcepts
						.indexOf(conceptConcerne);

				Axe axePrinc = new Axe(listeConcepts.get(indexConcept),
						listeConcepts.get(indexConceptConcerne),
						typeAssociationConcept.Principal, nbNA, nbChoix,
						classement, stat);

				listeAxes.add(axePrinc);
			}

			// On va maintenant chercher les axes complémentaires
			StmtIterator listAxesComplementaires = donnees
					.listStatements(new SimpleSelector(ligne.getSubject(),
							propAxeComplementaire, (RDFNode) null));
			
			System.out.println("parser 10");
			
			while (listAxesComplementaires.hasNext()) {

				Statement axeComplementaire = listAxesComplementaires.next();
				int nbNA = 0;
				int classement = 0;
				double stat = 0;
				Concept conceptConcerne = new Concept("");
				int nbChoix = 0;

				// On récupère le concept concerne
				StmtIterator testConceptConcerne = donnees
						.listStatements(new SimpleSelector(axeComplementaire
								.getObject().asResource(), propConceptConcerne,
								(RDFNode) null));
				if (testConceptConcerne.hasNext()) {
					conceptConcerne = new Concept(testConceptConcerne.next()
							.getResource().getLocalName());
				}

				// On récupère le nombre de valeur manquantes
				StmtIterator testNbNA = donnees
						.listStatements(new SimpleSelector(axeComplementaire
								.getObject().asResource(), propNbNA,
								(RDFNode) null));
				if (testNbNA.hasNext()) {
					nbNA = testNbNA.next().getObject().asLiteral().getInt();
				}

				// on récupère la statistique
				StmtIterator testStat = donnees
						.listStatements(new SimpleSelector(axeComplementaire
								.getObject().asResource(), propStatistiqueX2,
								(RDFNode) null));
				if (testStat.hasNext()) {
					stat = testStat.next().getObject().asLiteral().getDouble();
				}

				// On récupère le classement
				StmtIterator testClassement = donnees
						.listStatements(new SimpleSelector(axeComplementaire
								.getObject().asResource(), propClassement,
								(RDFNode) null));
				if (testClassement.hasNext()) {
					classement = testClassement.next().getObject().asLiteral()
							.getInt();
				}

				// On récupère le nombre de choix
				StmtIterator testNbChoix = donnees
						.listStatements(new SimpleSelector(axeComplementaire
								.getObject().asResource(), propNombreChoix,
								(RDFNode) null));
				if (testNbChoix.hasNext()) {
					nbChoix = testNbChoix.next().getObject().asLiteral()
							.getInt();
				}

				// On crée l'objet Java axe
				if (!listeConcepts.contains(conceptConcerne)) {
					listeConcepts.add(conceptConcerne);
				}

				int indexConceptConcerne = listeConcepts
						.indexOf(conceptConcerne);

				Axe axeComp = new Axe(listeConcepts.get(indexConcept),
						listeConcepts.get(indexConceptConcerne),
						typeAssociationConcept.Complementaire, nbNA, nbChoix,
						classement, stat);

				listeAxes.add(axeComp);
			}

		}
		
		System.out.println("je suis arrivée au bout de la méthode parser()");

	}

	public Model getModel() {
		return model;
	}

	public void setModel(Model model) {
		this.model = model;
	}

	public Model getDonnees() {
		return donnees;
	}

	public void setDonnees(Model donnees) {
		this.donnees = donnees;
	}

	public void copieConceptAsso() {
		for (int i = 0; i < listeAxes.size(); i++) {
			ajoutetConcept(listeAxes.get(i).getConcept());
			ajoutetConcept(listeAxes.get(i).getConceptAssocie());
		}
	}

	public void ajoutetConcept(Concept c) {

		if (listeConcepts.size() != 0) {
			boolean p = false;

			for (int i = 0; i < listeConcepts.size(); i++) {
				if (listeConcepts.get(i).equals(c)) {
					p = true;
				}
			}
			if (p != true) {
				listeConcepts.add(c);
			}
		} else {
			listeConcepts.add(c);
		}
	}

	/***
	 * Méthode qui affiche les résultats du parsing
	 */
	public void afficherParsing() {

		for (int i = 0; i < listeAxes.size(); i++) {
			Axe ass = listeAxes.get(i);
			System.out.println("Concept :" + ass.getConcept().getNom() + ", "
					+ "Concept concerné " + ass.getConceptAssocie().getNom());
		}
	}

	/*-------------------GETTERS ET SETTERS-------------------*/
	public List<Axe> getListeAxes() {
		return listeAxes;
	}

	public void setListeAxes(List<Axe> ontologieContext) {
		listeAxes = ontologieContext;
	}

	public List<Concept> getListeConcepts() {
		return listeConcepts;
	}

	public void setListeConcepts(List<Concept> listContextConcept) {
		this.listeConcepts = listContextConcept;
	}

	public static void setUniqueLecture(LectureFichierOrdre uniqueLecture) {
		LectureFichierOrdre.uniqueLecture = uniqueLecture;
	}

}